/**
 * Copyright (C), 2015-2019, XXX有限公司
 * FileName: ScheduleUtil
 * Author:   zhouheng
 * Date:     2019/6/25 23:09
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.zhouh.golden.util;

import com.zhouh.golden.domain.Job;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;

/**
 * 〈一句话功能简述〉<br> 
 * 〈工具类〉
 *
 * @author zhouheng
 * @create 2019/6/25
 * @since 1.0.0
 */
@Slf4j
public class ScheduleUtil {

    private static final String JOB_NAME = "TASK_";

    public static JobKey getJobKey(Long jobId){
        return JobKey.jobKey(JOB_NAME + jobId);
    }

    public static TriggerKey getTriggerKey(Long jobId){
        return TriggerKey.triggerKey(JOB_NAME + jobId);
    }

   /**
    * @description:  获取表达式触发器
    * @date: 2019/6/26 0:07
    * @author:zhouheng
    */
    public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId) {
        try {
            return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
        } catch (SchedulerException e) {
            log.error("获取Cron表达式失败", e);
        }
        return null;
    }


    /**
     * @description: 创建定时任务
     * @date: 2019/6/25 23:26
     * @author:zhouheng
     */
    public static void create(Scheduler scheduler, Job scheduleJob){
        // 1 创建JobDetail对象
        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put(Job.JOB_PARAM_KEY, scheduleJob);
        JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(scheduleJob.getJobId()))
                .setJobData(jobDataMap).build();

        // 2 创建表达式触发器调度
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression()).withMisfireHandlingInstructionDoNothing();
        // 3 按新的cronExpression表达式构建一个新的trigger
        CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(scheduleJob.getJobId()))
                .withSchedule(cronScheduleBuilder).build();

        try {
            // 4 根据jobdetail及cronExpression 创建定时任务
            scheduler.scheduleJob(jobDetail,cronTrigger);

            // 暂停任务
            if (StringUtils.equals(scheduleJob.getStatus(), Job.ScheduleStatus.PAUSE.getValue())) {
                pauseJob(scheduler, scheduleJob.getJobId());
            }
        } catch (SchedulerException e) {
            log.error("创建定时任务失败", e);
        }
    }

    /**
     * @description: 更新定时任务
     * @date: 2019/6/25 23:26
     * @author:zhouheng
     */
    public static void update(Scheduler scheduler, Job scheduleJob){
        try {
            // 表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
                    .withMisfireHandlingInstructionDoNothing();

            // 3 按新的cronExpression表达式构建一个新的trigger
            CronTrigger cronTrigger = getCronTrigger(scheduler,scheduleJob.getJobId());

            if (cronTrigger == null){
                throw new SchedulerException("获取Cron表达式失败");

            }else {
                cronTrigger = cronTrigger.getTriggerBuilder().withIdentity(getTriggerKey(scheduleJob.getJobId()))
                        .withSchedule(scheduleBuilder).build();

                // 参数
                cronTrigger.getJobDataMap().put(Job.JOB_PARAM_KEY, scheduleJob);
            }


            scheduler.rescheduleJob(getTriggerKey(scheduleJob.getJobId()), cronTrigger);

            // 暂停任务
            if (StringUtils.equals(scheduleJob.getStatus(), Job.ScheduleStatus.PAUSE.getValue())) {
                pauseJob(scheduler, scheduleJob.getJobId());
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }

    }

    public static void pauseJob(Scheduler scheduler, Long jobId){
        try {
            scheduler.pauseJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            log.error("暂停定时任务失败", e);
        }
    }

    public static void run(Scheduler scheduler, Job scheduleJob){
        try {
            // 参数
            JobDataMap dataMap = new JobDataMap();
            dataMap.put(Job.JOB_PARAM_KEY, scheduleJob);

            scheduler.triggerJob(getJobKey(scheduleJob.getJobId()), dataMap);
        } catch (SchedulerException e) {
            log.error("执行定时任务失败", e);
        }
    }

    /**
     * 恢复任务
     */
    public static void resumeJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.resumeJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            log.error("恢复定时任务失败", e);
        }
    }

    /**
     * 删除定时任务
     */
    public static void deleteScheduleJob(Scheduler scheduler, Long jobId) {
        try {
            scheduler.deleteJob(getJobKey(jobId));
        } catch (SchedulerException e) {
            log.error("删除定时任务失败", e);
        }
    }
}